package com.xypw.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.xypw.util.UploadDealer;


public class UploadServlet extends HttpServlet {
	
	private static final long serialVersionUID = -6197195477108554090L;
	
	private String fsp = File.separator;
	private String savePath = "";
	private String fileExt[] = null;
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setCharacterEncoding("UTF-8");
		String methodName = getMethodName(request);
		try {
			Method method = this.getClass().getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			method.invoke(this,request,response);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * AJAX上传，对应xheditor的文件上传
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	public void imgUpload(HttpServletRequest request, HttpServletResponse response) throws Exception{
		if(!ServletFileUpload.isMultipartContent(request)){//用 ServletFileUpload 类的静态方法 isMultipartContent 判断 request 是否是 multipart/form-data 类型
            imgUploadResp("不是上传请求！", "", response);
			return;
        }
        //创建 DiskFileItemFactory 对象
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //factory.setRepository(tempDir);设置缓存目录
        //超过1m的数据采用临时文件缓存
        factory.setSizeThreshold(1024 * 1024);
        ServletFileUpload upload = new ServletFileUpload(factory);
        //创建 ServletFileUpload 对象，构造的时候传一个 DiskFileItemFactory 对象进去
        upload.setFileSizeMax(1024 * 1024 * 2);//单个文件大小
        upload.setHeaderEncoding("UTF-8");//设置普通字段名称和文件字段的文件名所采用的字符集编码
        upload.setSizeMax(1024 * 1024 * 4);//最多上传2m的文件
        List list = null;
        try {
            list = upload.parseRequest(request);//解析 request 对象 得到一个包含 FileItem 对象的 list
        } catch (FileUploadException e) {
            e.printStackTrace();
            imgUploadResp("出现一个错误，可能是文件太大，请选择2MB以下的照片", "", response);
            return;
        }
        Iterator it = list.iterator();//遍历list
        while(it.hasNext()){
            FileItem fi = (FileItem)it.next();//类型转换
            if(fi.isFormField()){//判断该 FileItem 对象是否是一个普通表单类型
                String name = fi.getFieldName();//得到普通表单类型的表单名
                String content = fi.getString("UTF-8");//用指定编码得到普通表单的值
                request.setAttribute(name, content);//把键值放入 request 对象
            }else{
                try{
                    String filePathStr = fi.getName();//得到文件表单的值，就是用户本地的文件路径
                    //如果文件表单为空，则不处理
                    if(filePathStr.trim().equals("")){
                        continue;
                    }
                    //得到文件名在路径中的位置
                    int start = filePathStr.lastIndexOf("//");
                    //得到文件名
                    String fileName = filePathStr.substring(start + 1);
                    //创建上传上来的文件对象，存放文件的路径由配置中获取，文件名为当前毫秒数+后缀
                    String fileExt = getFileExt(fileName);
                    if(fileExt == null){
                    	imgUploadResp("文件类型错误！请重新选择", "", response);
                    	return;
                    }
                    DateFormat df = new SimpleDateFormat( "yyyyMMdd");
                    String dataTab = df.format(new Date());
                    String fileFullPath = savePath + dataTab + fsp;
                    
                    //判断路径上的目录是否存在，不存在就创建
                    File dirFile = new File(fileFullPath);
                    if( !dirFile.exists() ){
                    	dirFile.mkdirs();
                    }
                    
                    String fileFullName = System.currentTimeMillis() + "." + fileExt;
                    File pathDest = new File( fileFullPath, fileFullName );
                    //写文件
                    fi.write(pathDest);
                    
                    //得到文件表单的名称
                    //String name = fi.getFieldName();
                    //把表单名、文件名放入 request
                    //request.setAttribute(name, fileName);
                    
                    imgUploadResp("", request.getContextPath()+"/download/showNewsImg/"+dataTab+"?file="+fileFullName, response);
                    
                }catch(Exception e){
                    e.printStackTrace();
                    imgUploadResp("服务器端错误，请联系管理员", "", response);
                }finally{
                	//立即删除保存表单字段内容的临时文件
                    fi.delete();
                }
            }
        }
	}
	
	private String getMethodName(HttpServletRequest request){
		String path = request.getServletPath();
		String lastStr = path.substring(path.length()-1);
		if("/".equals(lastStr)){
			path = path.substring(0,path.length()-1);
		}
		return path.substring(path.lastIndexOf("/")+1);
	}
	
	private void imgUploadResp(String err, String msg, HttpServletResponse response) throws Exception{
		PrintWriter out = response.getWriter();
        out.print("{\"err\":\""+err+"\",\"msg\":\""+msg+"\"}");
        out.flush();
		out.close();
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		savePath = (String) config.getServletContext().getInitParameter("imgUploadPath");
		savePath = savePath.replaceAll("/", Matcher.quoteReplacement(fsp));
		String fileExtStr =  (String) this.getServletContext().getInitParameter("imgUploadExt");
		fileExt = fileExtStr.split(",");
	}
	
	/**
	 * 取得文件名后缀，并限制一定类型的文件上传
	 * 没有后缀如果不是符合的上传类型或者没有后缀，则返回null；
	 * @return
	 */
	private String getFileExt(String fileName){
		if(fileName.indexOf(".") == -1){
			return null;
        }
		String ext = fileName.substring(fileName.lastIndexOf(".")+1);
		for (String _fileExt : fileExt) {
			if(_fileExt.equals(ext)){
				return ext;
			}
		}
		return null;
	}

	public String getFsp() {
		return fsp;
	}

	public void setFsp(String fsp) {
		this.fsp = fsp;
	}

	public String getSavePath() {
		return savePath;
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	public String[] getFileExt() {
		return fileExt;
	}

	public void setFileExt(String[] fileExt) {
		this.fileExt = fileExt;
	}
	
}
